package Model.Draw.Entities;

import Model.Core.IEntity;
import Model.Core.Impl.LinkEntity;
import Model.Draw.Entities.Impl.EntityJoint;
import Model.Draw.Entities.Impl.LinkLine;
import Model.Draw.ICommunicatorDraw;
import Model.Draw.IEntityDraw;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Line2D;
import java.util.ArrayList;

/**
 * Projeto de TCC: Editor de Diagramas de Comunicação em UML.
 * @author Jose
 */
public class LinkDraw implements IEntityDraw {

    private LinkEntity linkEntity;
    private LinkLine linkLine;
    private ICommunicatorDraw sourceDraw;
    private ObjectDraw targetDraw;
    private boolean selected;
    private Line2D line;
    private ArrayList<Line2D> linesAutoLink;

    public LinkDraw(LinkLine linkLine, ICommunicatorDraw sourceDraw, ObjectDraw targetDraw) {
        this.linkLine = linkLine;
        this.sourceDraw = sourceDraw;
        this.targetDraw = targetDraw;
        linesAutoLink = new ArrayList();

    }

    @Override
    public void setEntity(IEntity entity) {
        linkEntity = (LinkEntity) entity;
    }

    @Override
    public IEntity getEntity() {
        return linkEntity;
    }

    @Override
    public void draw(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        if (sourceDraw instanceof ICommunicatorDraw) {
            g2.setColor(getColor());
            g2.setStroke(new BasicStroke(2));
            if (((ICommunicatorDraw) sourceDraw).equals(targetDraw)) {
                double x1 = targetDraw.getTop().getJoint().getX().getCoordinate() + ((targetDraw.getRight().getJoint().getX().getCoordinate() - targetDraw.getTop().getJoint().getX().getCoordinate()) / 2);
                double y3 = targetDraw.getTop().getJoint().getY().getCoordinate() + ((targetDraw.getRight().getJoint().getY().getCoordinate() - targetDraw.getTop().getJoint().getY().getCoordinate()) / 2);
                linesAutoLink.clear();
                linesAutoLink.add(new Line2D.Double(x1, targetDraw.getTop().getJoint().getY().getCoordinate() - 1, x1, targetDraw.getTop().getJoint().getY().getCoordinate() - 20));
                linesAutoLink.add(new Line2D.Double(x1, targetDraw.getTop().getJoint().getY().getCoordinate() - 20, targetDraw.getRight().getJoint().getX().getCoordinate() + 10, targetDraw.getTop().getJoint().getY().getCoordinate() - 20));
                linesAutoLink.add(new Line2D.Double(targetDraw.getRight().getJoint().getX().getCoordinate() + 10, targetDraw.getTop().getJoint().getY().getCoordinate() - 20, targetDraw.getRight().getJoint().getX().getCoordinate() + 10, y3));
                linesAutoLink.add(new Line2D.Double(targetDraw.getRight().getJoint().getX().getCoordinate() + 10, y3, targetDraw.getRight().getJoint().getX().getCoordinate() + 1, y3));
                for (Line2D l : linesAutoLink) {
                    g2.draw(l);
                }
            } else {
                if (sourceDraw instanceof ICommunicatorDraw) {
                    EntityJoint j1 = sourceDraw.findNearstJointOf(targetDraw);
                    EntityJoint j2 = targetDraw.findNearstJointOf(sourceDraw);

                    line = new Line2D.Float((int) j1.getX().getCoordinate(), (int) j1.getY().getCoordinate(), (int) j2.getX().getCoordinate(), (int) j2.getY().getCoordinate());
                    g2.draw(line);
                }
            }
        }
    }

    public Color getColor() {
        if (selected) {
            return Color.RED;
        }
        return Color.BLACK;
    }

    @Override
    public boolean contains(int x, int y) {
        int HIT_BOX_SIZE = 3;
        int boxX = x - HIT_BOX_SIZE / 2;
        int boxY = y - HIT_BOX_SIZE / 2;
        int width = HIT_BOX_SIZE;
        int height = HIT_BOX_SIZE;
        boolean contains = false;
        if (sourceDraw instanceof ObjectDraw && ((ObjectDraw) sourceDraw).equals(targetDraw)) {
            int index = 0;
            while (!contains && index < linesAutoLink.size()) {
                if(linesAutoLink.get(index).intersectsLine(boxX, boxY, width, height))
                    contains = true;
                index++;
            }
        } else {
            if (line != null && line.intersects(boxX, boxY, width, height)) {
                contains = true;
            }
        }
        return contains;
    }

    @Override
    public void select() {
        selected = true;
    }

    @Override
    public void unselect() {
        selected = false;
    }

    @Override
    public void move(int diffX,
            int diffY) {
        //    throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void rename(String newName) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public LinkLine getLinkLine() {
        return linkLine;
    }

    public ICommunicatorDraw getSourceDraw() {
        return sourceDraw;
    }

    public void setSourceDraw(ICommunicatorDraw sourceDraw) {
        this.sourceDraw = sourceDraw;
    }

    public ObjectDraw getTargetDraw() {
        return targetDraw;
    }

    public void setTargetDraw(ObjectDraw targetDraw) {
        this.targetDraw = targetDraw;
    }

    public Line2D getLineDraw() {
        return line;
    }
    
    public Line2D getLineDrawAutoMessage(){
        return linesAutoLink.get(1);
    }
}